﻿{******************************************************************************}
{                                                                              }
{                               UNIT FileStream                                }
{                                                                              }
{  В этом модуле содержится потомок TFileStream, в котором решена проблема     }
{  открытия/создания файла с проверкой его существования, а также проблема     }
{  совместного доступа к файлу из других процессов системы.                    }
{                                                                              }
{                       Copyright © 2012 by Xcentric                           }
{                                                                              }
{http://code.google.com/p/powered-by-delphi/                                   }
{******************************************************************************}

unit FileStream;

interface

uses
  Classes, SysUtils, Math;

type

  TFileStreamFactory = class
    public
      class function CreateFile(const AFileName : String) : TFileStream;
  end;

  TFileStreamHelper = class helper for TFileStream
    public
      procedure PointToEnd;
      function  ReadString(const Size : Integer) : String;
      procedure WriteString(const S : String);
  end;

implementation

type

  TDefaultFileStream = class (TFileStream)
    public
      constructor Create(const AFileName : String);
  end;

{ TDefaultFileStream }

constructor TDefaultFileStream.Create(const AFileName : String);
  var
    sFileName, sFileDir : String;
begin
  sFileName := ExpandFileName(AFileName);
  sFileDir  := ExtractFileDir(sFileName);

  If DirectoryExists(sFileDir) Then
    Inherited Create(sFileName,
      IfThen(FileExists(sFileName), fmOpenWrite Or fmShareDenyWrite, fmCreate))
  Else
    If Not ForceDirectories(sFileDir) Then
      RaiseLastOSError
    Else
      Inherited Create(sFileName, fmCreate);
end;

{ TFileStreamHelper }

procedure TFileStreamHelper.PointToEnd;
begin
  Position := Size;
end;

function TFileStreamHelper.ReadString(const Size : Integer) : String;
  var
    SS : TStringStream;
begin
  SS := TStringStream.Create;
  Try
    SS.CopyFrom(Self, Size);
    Result := SS.DataString;
  Finally
    FreeAndNil(SS);
  End;
end;

procedure TFileStreamHelper.WriteString(const S : String);
  var
    SS : TStringStream;
begin
  SS := TStringStream.Create;
  Try
    SS.WriteString(S);
    SS.SaveToStream(Self);
  Finally
    FreeAndNil(SS);
  End;
end;

{ TFileStreamFactory }

class function TFileStreamFactory.CreateFile(
  const AFileName : String) : TFileStream;
  var
    bJustCreated : Boolean;
begin
  bJustCreated := Not FileExists(AFileName);
  Result := TDefaultFileStream.Create(AFileName);

  If bJustCreated Then
  begin
    FreeAndNil(Result);
    Result := TDefaultFileStream.Create(AFileName);
  end;
end;

end.